#include "ULGfx_Statistic.h"
#include "ULGfx_History.h"
#include <SDL/sprig.h>

void ULG_Statistic::SetStartXY(VSDL_Point point)
{
	startXY = point;
}

void ULG_Statistic::GetHighestN(int *arr, int &count, ULC_PositionInfo *posInfo)
{
	list<ULC_BallFrequency> tmpList;
	list<ULC_BallFrequency>::iterator iter;
	int index = 0;

	memset(arr, 0, count * sizeof(int));
	posInfo->GetHighestRates(tmpList, count);
	
	for (iter = tmpList.begin(); iter != tmpList.end(); iter++){
		arr[index++] = (*iter).number;
	}
}

void ULG_Statistic::GetLowestN(int *arr, int &count, ULC_PositionInfo *posInfo){
	list<ULC_BallFrequency> tmpList;
	list<ULC_BallFrequency>::iterator iter;
	int index = 0;

	memset(arr, 0, count * sizeof(int));
	posInfo->GetLowestRates(tmpList, count);
	
	for (iter = tmpList.begin(); iter != tmpList.end(); iter++){
		arr[index++] = (*iter).number;
	}
}

int ULG_Statistic::Show(SDL_Surface *destSurf, int nSerials, ULC_Serial *serials, bool useSorted)
{	
	VSDL_RGB rgb(0, 0, 0);
	ULC_Statistic stat;
	ULC_Balls *balls;	
	ULC_PositionInfo *posInfo;
	ULG_History *ulgHistory = ULG_History::Instance();
	int i, j;
	int first[5];
	int gap;

	if (destSurf == NULL || (gfxFlags & ULG_STATISTIC_F_FONT_SET) == 0 || nSerials < ULG_STATISTIC_LEAST_SERIALS || serials == NULL){
		return -1;
	}


	//Fix boundary
	gap = ulgHistory->CaculateGap(serials, ulgHistory->GetLatestSerial());
	
	if ((gap + 2) < ULG_STATISTIC_LEAST_SERIALS){
		nSerials = ULG_STATISTIC_LEAST_SERIALS;
		serials = ulgHistory->GetLatestSerials(nSerials);
	}

	stat.ParseSerials(nSerials, serials);

	currentXY = startXY;
	//Draw tips
	sprintf(msgBuffer, "Start Serial: %-10d Date: %s", serials[0].sn, serials[0].date);
	msg.SetFgColor(0, 0, 0);
	msg.SetText(msgBuffer);
	msg.Blit(destSurf, currentXY);
	//Draw Rect for tips
	SPG_Rect(destSurf, currentXY.x, currentXY.y, currentXY.x + tipRectWidth, currentXY.y + tipRectHeight, rgb.GetRGB32(destSurf));
	currentXY.y += fontHeight;
	
	//Draw UL_BALL_MAX_RED bars

	bar.SetTitleColor(250, 120, 120);
	for (i = 0; i < UL_BALL_MAX_RED; i++){
		sprintf(msgBuffer, "%02d", i + 1);
		bar.SetTitle(msgBuffer);
		SPG_Rect(destSurf, currentXY.x, currentXY.y, currentXY.x + fontWidth, currentXY.y + fontHeight, rgb.GetRGB32(destSurf));
		bar.Blit(destSurf, currentXY);
		currentXY.x += fontWidth;
	}
	
	currentXY.y += fontHeight;
	//Draw red ones
	bar.SetRectFillColor(50, 200, 50);

	rgb.SetRGB(100, 100, 200);
	SPG_RectFilled(destSurf, startXY.x, currentXY.y, startXY.x + tipRectWidth, currentXY.y + nSerials * fontHeight, rgb.GetRGB32(destSurf));
	rgb.SetRGB(40, 40, 40);
	for (i = 0; i < nSerials; i++){
		//Only show sorted reds
		balls = &serials[i].sortedBalls;
		
		for (j = 0; j < UL_RED_BALLS_COUNT; j++){
			currentXY.x = startXY.x + (balls->reds[j] - 1) * fontWidth;
			//Draw Rect
			SPG_RectFilled(destSurf, currentXY.x, currentXY.y, currentXY.x + fontWidth, currentXY.y + fontHeight, rgb.GetRGB32(destSurf));
			sprintf(msgBuffer, "%02d", balls->reds[j]);
			bar.SetTitle(msgBuffer);
			bar.Blit(destSurf, currentXY);
		}

		currentXY.y += fontHeight;
	}

	rgb.SetRGB(0, 0, 0);
	//Draw vertical lines
	currentXY.x = startXY.x;
	for (i = 0; i < UL_BALL_MAX_RED; i++){
		SPG_Line(destSurf, currentXY.x, startXY.y + fontHeight, currentXY.x, currentXY.y, rgb.GetRGB32(destSurf));
		currentXY.x += fontWidth;
	}

	//Draw horizontal lines
	currentXY.y -= nSerials * fontHeight;
	for (i = 0; i < nSerials; i++){
		SPG_Line(destSurf, startXY.x, currentXY.y, startXY.x + tipRectWidth, currentXY.y, rgb.GetRGB32(destSurf));
		currentXY.y += fontHeight;
	}

	//Draw UL_BALL_MAX_BLUE Blue bars
	currentXY.x = startXY.x;
	
	bar.SetTitleColor(20, 20, 250);
	for (i = 0; i < UL_BALL_MAX_BLUE; i++){
		sprintf(msgBuffer, "%02d", i + 1);
		bar.SetTitle(msgBuffer);
		SPG_Rect(destSurf, currentXY.x, currentXY.y, currentXY.x + fontWidth, currentXY.y + fontHeight, rgb.GetRGB32(destSurf));
		bar.Blit(destSurf, currentXY);
		currentXY.x += fontWidth;
	}

	SPG_Rect(destSurf, currentXY.x, currentXY.y, startXY.x + tipRectWidth, currentXY.y + fontHeight, rgb.GetRGB32(destSurf));
	//Top 5 and Bottom 5
	msg.SetText("Top 5 highest and Top 5 lowest");
	currentXY.x += fontWidth;
	msg.Blit(destSurf, currentXY);

	currentXY.y += fontHeight;
	//Draw blue ones

	rgb.SetRGB(250, 120, 120);
	SPG_RectFilled(destSurf, startXY.x, currentXY.y, startXY.x + UL_BALL_MAX_BLUE * fontWidth, currentXY.y + nSerials * fontHeight, rgb.GetRGB32(destSurf));
	rgb.SetRGB(200, 200, 200);
	for (i = 0; i < nSerials; i++){
		balls = &serials[i].sortedBalls;
		
		currentXY.x = startXY.x + (balls->blue - 1) * fontWidth;
		//Draw Rect
		SPG_RectFilled(destSurf, currentXY.x, currentXY.y, currentXY.x + fontWidth, currentXY.y + fontHeight, rgb.GetRGB32(destSurf));
		sprintf(msgBuffer, "%02d", balls->blue);
		bar.SetTitle(msgBuffer);
		bar.Blit(destSurf, currentXY);
		currentXY.y += fontHeight;
	}

	rgb.SetRGB(0, 0, 0);
	SPG_Rect(destSurf, startXY.x, startXY.y, startXY.x + tipRectWidth, currentXY.y, rgb.GetRGB32(destSurf));
	//Draw vertical lines
	currentXY.x = startXY.x + fontWidth;

	for (i = 0; i < UL_BALL_MAX_BLUE; i++){
		SPG_Line(destSurf, currentXY.x, startXY.y + fontHeight, currentXY.x, currentXY.y, rgb.GetRGB32(destSurf));
		currentXY.x += fontWidth;
	}
	//Draw horizontal lines
	currentXY.y -= nSerials * fontHeight;
	int tmpWidth = UL_BALL_MAX_BLUE * fontWidth;

	for (i = 0; i < nSerials; i++){
		SPG_Line(destSurf, startXY.x, currentXY.y, startXY.x + tmpWidth, currentXY.y, rgb.GetRGB32(destSurf));
		currentXY.y += fontHeight;
	}

	//Draw top 5 and bottom 5
	currentXY.y -= nSerials * fontHeight;
	
	if (useSorted){
		posInfo = stat.GetSortedRedInfo(0);
	}else{
		posInfo = stat.GetOutRedInfo(0);
	}

	msg.SetFgColor(250, 80, 80);
	for (i = 0; i < UL_RED_BALLS_COUNT; i++){
		int count = 5;

		GetHighestN(first, count, posInfo + i);

		sprintf(msgBuffer, "Highest Red %d: %d %d %d %d %d", i + 1, first[0], first[1], first[2], first[3], first[4]);

		msg.SetText(msgBuffer);
		msg.Blit(destSurf, currentXY);
		currentXY.y += fontHeight;
	}

	//Draw a line
	SPG_Line(destSurf, startXY.x + UL_BALL_MAX_BLUE * fontWidth, currentXY.y + 1, startXY.x + tipRectWidth, currentXY.y + 1, rgb.GetRGB32(destSurf));

	for (i = 0; i < UL_RED_BALLS_COUNT; i++){
		int count = 5;

		GetLowestN(first, count, posInfo + i);

		sprintf(msgBuffer, "Lowest Red(%d): %02d %02d %02d %02d %02d", i + 1, first[0], first[1], first[2], first[3], first[4]);
		msg.SetText(msgBuffer);
		msg.Blit(destSurf, currentXY);
		currentXY.y += fontHeight;
	}

	//Draw a line
	SPG_Line(destSurf, startXY.x + UL_BALL_MAX_BLUE * fontWidth, currentXY.y + 1, startXY.x + tipRectWidth, currentXY.y + 1, rgb.GetRGB32(destSurf));
	//Blue
	msg.SetFgColor(20, 20, 250);
	
	{
		int count = 5;
		posInfo = stat.GetBlueInfo();
		GetHighestN(first, count, posInfo);
		sprintf(msgBuffer, "Higheset 5 Blue: %02d %02d %02d %02d %02d", i + 1, first[0], first[1], first[2], first[3], first[4]);
		msg.SetText(msgBuffer);
		msg.Blit(destSurf, currentXY);
		
		currentXY.y += fontHeight;
		count = 5;
		GetLowestN(first, count, posInfo);
		sprintf(msgBuffer, "Lowest  5 Blue: %02d %02d %02d %02d %02d", i + 1, first[0], first[1], first[2], first[3], first[4]);
		msg.SetText(msgBuffer);
		msg.Blit(destSurf, currentXY);
		
	}

	return 0;
}

int ULG_Statistic::Show(SDL_Surface *destSurf, int nSerials, ULC_Serial *serials)
{
	return Show(destSurf, nSerials, serials, true);
}

int ULG_Statistic::SetFont(VSDL_Font *font)
{
	if (font == NULL){
		return -1;
	}

	msg.SetFont(font);
	bar.SetFont(font);
	msg.SetText("Temp");
	bar.SetTitle("55");
	bar.GetTitleSize(fontWidth, fontHeight);
	bar.SetRectFillColor(50, 200, 50);
	//Should be in constructor
	tipRectWidth = UL_BALL_MAX_RED * fontWidth;
	tipRectHeight = fontHeight;

	gfxFlags |= ULG_STATISTIC_F_FONT_SET;
	return 0;
}
